#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import json
import os
from flask import Flask, request, jsonify
from config import path
from function import json_file_to_dict, dict_to_json_write_file, pic_decode, excel_writer, sendEmail
import datetime
from celery import Celery, platforms
from flask_mail import Mail, Message


def make_celery(app):
    celery = Celery(
        app.import_name,
        backend=app.config['CELERY_RESULT_BACKEND'],
        broker=app.config['CELERY_BROKER_URL']
    )
    celery.conf.update(app.config)

    class ContextTask(celery.Task):
        def __call__(self, *args, **kwargs):
            with app.app_context():
                return self.run(*args, **kwargs)

    celery.Task = ContextTask
    return celery


app = Flask(__name__)

platforms.C_FORCE_ROOT = True
# Celery configuration
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'

# Initialize Celery
# celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery = make_celery(app)


@celery.task(name=app.name, bind=True)
def information_maker(self, input_params, new_path, timestamp):
    """跑费时间的基础程序"""
    # new_path, input_params
    dict_to_json_write_file("{0}/{1}".format(new_path, "config.json"), input_params['plist'])
    # 保存电站照片
    for i in range(len(input_params['plist']['station_pics'])):
        pic_decode(input_params['plist']['station_pics'][i], new_path, "station_" + str(i))
    self.update_state(state='PROGRESS',
                      meta={'current': 30, 'total': 100,
                            'status': '电站照片上传完成'})
    # 保存交通照片
    for i in range(len(input_params['plist']['transp_pics'])):
        pic_decode(input_params['plist']['transp_pics'][i], new_path, "trans_" + str(i))
    self.update_state(state='PROGRESS',
                      meta={'current': 50, 'total': 100,
                            'status': '交通照片上传完成'})
    # 保存Excel
    excel_name = "{0}_{1}_{2}.xlsx".format("电站详细信息", input_params['plist']['station_no'], timestamp)
    excel_writer(new_path, excel_name, input_params['plist'])
    self.update_state(state='PROGRESS',
                      meta={'current': 99, 'total': 100,
                            'status': '信息整理成功'})
    return {'current': 100, 'total': 100, 'status': '信息上传任务完成', 'result': 42}


# 发送邮件
@app.route('/zw/v1.0/email/send', methods=['POST'])
def email_send():
    # 整理信息
    input_params = json.loads(request.get_data(as_text=True))
    try:
        sendEmail(input_params)
        return jsonify({"msg": "发送成功",
                        "data": [],
                        "code": 0})
    except UserWarning:
        return jsonify({"msg": "发送失败",
                        "data": [],
                        "code": 1})


#
@app.route('/hello')
def hello_world():
    return 'Hello World!'


# 查询电站列表
@app.route('/zw/v1.0/forms/check', methods=['POST'])
def forms_check():
    #
    input_params = json.loads(request.get_data(as_text=True))
    obj_path = "{0}/{1}".format(path, '/'.join(input_params['area class']))
    if os.path.exists(obj_path):
        string = []
        dir_list = [name for name in os.listdir(obj_path) if os.path.isdir(os.path.join(obj_path, name))]
        try:
            for dirname in dir_list:
                orig_up = [name for name in os.listdir(obj_path + "/" + dirname) if
                           os.path.isdir(os.path.join(obj_path + "/" + dirname, name))]
                latest_up = sorted(orig_up, key=lambda x: int(x[:-1]))[-1]
                string.append({"station_no": dirname, 
                               "station_name": 
                                   json_file_to_dict("{0}/{1}/{2}/{3}".format(obj_path, dirname, latest_up, 
                                                                              "config.json"))[
                                                                                            'station_name']})
            return jsonify({"msg": "请求成功",
                            "data": string,
                            "code": 0})
        except UserWarning:
            return jsonify({"msg": "请求失败",
                            "data": [],
                            "code": 1})
    else:
        return jsonify({"msg": "请求成功",
                        "data": [],
                        "code": 0})


# 查询电站具体信息
@app.route('/zw/v1.0/forms/information_check', methods=['POST'])
def information_check():
    input_params = json.loads(request.get_data(as_text=True))
    obj_path = "{0}/{1}/{2}".format(path, '/'.join(input_params['area class']), input_params['station_no'])
    # noinspection PyBroadException
    try:
        orig_up = [name for name in os.listdir(obj_path) if os.path.isdir(os.path.join(obj_path, name))]
        latest_up = sorted(orig_up, key=lambda x: int(x[:-1]))[-1]
        try:
            result = json_file_to_dict("{0}/{1}/{2}".format(obj_path, latest_up, "config.json"))
            return jsonify({"msg": "请求成功",
                            "data": result,
                            "code": 0})
        except Exception as e:
            return jsonify({"msg": "配置信息载入失败" + str(e),
                            "data": [],
                            "code": 1})
    except Exception as e:
        return jsonify({"msg": "请求失败:" + repr(e),
                        "data": [],
                        "code": 1})


# 新增电站及信息
@app.route('/zw/v1.0/forms/information_new', methods=['POST'])
def information_new():
    input_params = json.loads(request.get_data(as_text=True))
    obj_path = "{0}/{1}".format(path, '/'.join(input_params['area']['area class']))
    if os.path.exists(obj_path):
        dir_list = [name for name in os.listdir(obj_path) if os.path.isdir(os.path.join(obj_path, name))]
        input_params['plist']['station_no'] = "{0}{1}".format(input_params['area']['area number'],
                                                              str(len(dir_list)).zfill(4))  # 尾数4位数
    else:
        input_params['plist']['station_no'] = "{0}{1}".format(input_params['area']['area number'],
                                                              str(0).zfill(4))  # 尾数4位数
    timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    new_path = "{0}/{1}/{2}".format(obj_path, input_params['plist']['station_no'], timestamp)
    try:
        os.makedirs(new_path)
    except Exception as e:
        return jsonify({"msg": "操作失败:" + repr(e),
                        "data": [],
                        "code": 1})
    task = information_maker.apply_async(args=[input_params, new_path, timestamp])
    # task = information_maker.delay(args=[input_params, new_path, timestamp])
    return jsonify({"msg": "请求成功",
                    "data": {'task id': task.id},
                    "code": 0})


# 修改电站信息
@app.route('/zw/v1.0/forms/information_modify', methods=['POST'])
def information_modify():
    input_params = json.loads(request.get_data(as_text=True))
    obj_path = "{0}/{1}".format(path, '/'.join(input_params['area']['area class']))
    timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    new_path = "{0}/{1}/{2}".format(obj_path, input_params['plist']['station_no'], timestamp)
    try:
        os.makedirs(new_path)
    except Exception as e:
        return jsonify({"msg": "操作失败:" + repr(e),
                        "data": [],
                        "code": 1})
    task = information_maker.apply_async(args=[input_params, new_path, timestamp])
    return jsonify({"msg": "请求成功",
                    "data": {'task id': task.id},
                    "code": 0})


# 查询后台操作进程
@app.route('/zw/v1.0/taskstatus/check', methods=['POST'])
def taskstatus_check():
    task_id = json.loads(request.get_data(as_text=True))['task_id']
    task = information_maker.AsyncResult(task_id)
    if task.state == 'PENDING':  # 服务还没有启动
        response = {
            'state': task.state,
            'current': 0,
            'total': 1,
            'status': 'Pending...'
        }
    elif task.state != 'FAILLURE':
        response = {
            'state': task.state,
            'current': task.info.get('current', 0),
            'total': task.info.get('total', 1),
            'status': task.info.get('status')
        }
        if 'result' in task.info:
            response['result'] = task.info['result']
    else:
        response = {
            'state': task.state,
            'current': 1,
            'total': 1,
            'status': str(task.info),
        }
    return jsonify(response)


if __name__ == '__main__':
    app.run(
        host='0.0.0.0',
        port=443,
        ssl_context=('cert/db.funnyin.cn.pem', 'cert/db.funnyin.cn.key')
        # port=5001,
        # debug=True
    )
